﻿namespace OpenPasteSpider
{
    /// <summary>
    /// 集群模式 master的选举 node状态的变更 内部通知的归总notice
    /// </summary>
    public class SlaveHostedService : IHostedService
    {

        /// <summary>
        /// 
        /// </summary>
        private IServiceProvider _serviceProvider;

        private ILogger<SlaveHostedService> _logger;

        private ChannelHelper _channelHelper;

        private readonly CommandTaskHandler _commandHandler;

        private readonly RecoveryTaskHandler _recoveryTaskHandler;

        private readonly NoticeTaskHanlder _noticeHanlder;

        private readonly InitUpdateHandler _systemInitAndUpdateHandler;

        private readonly StatusTaskHandler _statustaskHandler;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <param name="logger"></param>
        /// <param name="channelHelper"></param>
        /// <param name="recoveryTaskHandler"></param>
        /// <param name="systemInitAndUpdateHandler"></param>
        /// <param name="noticeHanlder"></param>
        /// <param name="commandTaskHandler"></param>
        /// <param name="appCacheHelper"></param>
        /// <param name="statusTaskHandler"></param>
        public SlaveHostedService(
            IServiceProvider serviceProvider,
            ILogger<SlaveHostedService> logger,
            ChannelHelper channelHelper,
            RecoveryTaskHandler recoveryTaskHandler,
            InitUpdateHandler systemInitAndUpdateHandler,
            NoticeTaskHanlder noticeHanlder,
            CommandTaskHandler commandTaskHandler,
            ICacheHelper appCacheHelper,
            StatusTaskHandler statusTaskHandler
            )
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
            _channelHelper = channelHelper;
            _recoveryTaskHandler = recoveryTaskHandler;
            _systemInitAndUpdateHandler = systemInitAndUpdateHandler;
            _commandHandler = commandTaskHandler;
            _noticeHanlder = noticeHanlder;
            _statustaskHandler = statusTaskHandler;
        }

        /// <summary>
        /// slave健康检查计时器
        /// </summary>
        private System.Timers.Timer _timerhealth;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine($"{DateTime.Now} SlaveHostedService Start! MachineName:{Environment.MachineName}");
            //_tasklist = new List<TaskInfoDto>();
            //_nodelist = new List<SlaveNodeItem>();


            using var scop = _serviceProvider.CreateScope();
            using var _dbContext = scop.ServiceProvider.GetRequiredService<IOpenPasteSpiderDbContext>();

            //检查是否有升级
            await _systemInitAndUpdateHandler.DoInitAndUpdateAsync(_dbContext);

            //处理最后一次未处理的任务
            await _commandHandler.DoUnFinishPlanAsync(_dbContext, "");

            //集群心跳包监测
            _timerhealth = new System.Timers.Timer();
            _timerhealth.Interval = 1000;
            _timerhealth.Elapsed += _timerhealth_Elapsed;
            _timerhealth.AutoReset = true;
            _timerhealth.Start();

            _ = ReadCommandChannel();

            _ = ReadChannelNotice();

            _logger.LogWarning("System.SlaveHostService Start!");
        }

        /// <summary>
        /// 处理队列中的命令
        /// </summary>
        private async Task ReadCommandChannel(CancellationToken task = default)
        {
            while (!task.IsCancellationRequested)
            {
                try
                {
                    var info = await _channelHelper.CommandPlanChannel.Reader.ReadAsync();
                    if (info != null && info != default)
                    {
                        await _commandHandler.DoCommandPlanAsync(info.planid);
                    }
                }
                catch (Exception exl)
                {
                    _logger.LogException(exl);
                    await Task.Delay(1000);
                }
            }
        }

        /// <summary>
        /// 读取队列中的消息，消息通知 节点通知给master就行了，最终由master统一处理
        /// </summary>
        private async Task ReadChannelNotice(CancellationToken task = default)
        {
            while (!task.IsCancellationRequested)
            {
                try
                {
                    var info = await _channelHelper.ChannelNotice.Reader.ReadAsync();
                    if (info != null && info != default)
                    {
                        _logger.LogWarning(Newtonsoft.Json.JsonConvert.SerializeObject(info));
                        await _noticeHanlder.DoSendNoticeAsync(info);
                    }
                }
                catch (Exception exl)
                {
                    _logger.LogException(exl);
                    await Task.Delay(1000);
                }
            }
        }

        /// <summary>
        /// 集群心跳包监测
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _timerhealth_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            var now = DateTime.Now;

            var second = now.ToUnixTimeSeconds();

            var timestr = now.ToString("yyyy-MM-dd HH:mm:ss");

            //凌晨3点进行资源回收
            if (timestr.EndsWith("03:00:00"))
            {

                _recoveryTaskHandler.DoRecoveryAsync();

            }
            //每隔5分钟收集各个状态数据
            if (second % 300 == 0)
            {
                _statustaskHandler.DoReadStatsAsync(null, null);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task StopAsync(CancellationToken cancellationToken)
        {
            //throw new NotImplementedException();
            return Task.CompletedTask;
        }



    }
}
